package com.dns.server.secondary;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import com.dns.message.DNS_Message;
import com.dns.util.Constants;

public class SecondaryServer {
	
	public static DatagramSocket requestListenerSocket;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try
		{
		
		/*
		 * Parse the command line arguments.
		 */
			System.out.println("Reading Command Line Arguments");
			Configurations.parseCommandLineArguments(args);
			DomainDataHandler.initialize();
			System.out.println("\nReading Domain Data");
			DomainDataHandler.readDomainDataFile();
			requestListenerSocket = new DatagramSocket(Configurations.portForRequests);
			System.out.println("\nRegistering to Primary Server");
			registerToPrimaryServer();
			System.out.println("\nProcessing Requests");
			while(true)
			{
				try
				{
					byte []dataBuffer = new byte[Constants.DATA_BUFFER_SIZE];
					DatagramPacket receivedPacket;
					receivedPacket = new DatagramPacket(dataBuffer, dataBuffer.length);
					requestListenerSocket.receive(receivedPacket);
					RequestHandlerThread requestHandlerThread = new RequestHandlerThread(receivedPacket);
					requestHandlerThread.start();
				}catch(Exception exception)
				{ 
					System.err.println("Exception @SecondaryServer: "+exception.getMessage());
				}
			}
			
		
		}catch(Exception exception)
		{ 
			System.err.println("Exception @SecondaryServer: "+exception.getMessage());
		}
		
	}
	
	private static void registerToPrimaryServer()
	{
		DNS_Message msg = new DNS_Message();
		msg.setDomainName(Configurations.domain);
		msg.setIp_address(Configurations.myIPddress);		
		msg.setClientAddress(Configurations.myIPddress);
		msg.setClientPort(Configurations.portForRequests);
		msg.setMsgType(Constants.MSG_REGISTER);
		msg.setSource(Constants.SECONDARY);
		msg.setResult(Constants.SUCCESS);
		sendMessage(msg);
		//System.out.println("MSG SENT - REGISTER");
	}
	
	public static void sendMessage(DNS_Message msg)
	{
		printMessage(msg);
		
		DatagramPacket sendPacket;
		byte []buff = new byte[Constants.DATA_BUFFER_SIZE];
	
		ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
		ObjectOutputStream objectOut;
		try {
			objectOut = new ObjectOutputStream(byteOut);
			objectOut.writeObject(msg);
			buff =byteOut.toByteArray();
			sendPacket = new DatagramPacket(buff, buff.length, InetAddress.getByName(Configurations.primaryServerIP), Configurations.primaryServerPortForResponse);
			//System.out.println("Message Sending: To IP: "+Configurations.primaryServerIP+" PORT: "+Configurations.primaryServerPortForResponse);
			requestListenerSocket.send(sendPacket);
		} catch (IOException e) {
			System.out.println(" : Exception while creating the serializing or writing the DNS_Message object");
			e.printStackTrace();
		}
		finally{
			byteOut=null;
			objectOut=null;
			buff=null;
		}		
	}

	public static void sendMessageToClient(String clientIP, int clientPort, DNS_Message msg)
	{
		printMessage(msg);
		
		DatagramPacket sendPacket;
		byte []buff = new byte[Constants.DATA_BUFFER_SIZE];
	
		ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
		ObjectOutputStream objectOut;
		try {
			objectOut = new ObjectOutputStream(byteOut);
			objectOut.writeObject(msg);
			buff =byteOut.toByteArray();
			sendPacket = new DatagramPacket(buff, buff.length, InetAddress.getByName(clientIP), clientPort);
			requestListenerSocket.send(sendPacket);
		} catch (IOException e) {
			System.out.println(" : Exception while creating the serializing or writing the DNS_Message object");
			e.printStackTrace();
		}
		finally{
			byteOut=null;
			objectOut=null;
			buff=null;
		}		
	}
	
	public static void printMessage(DNS_Message msg)
	{
		String source = msg.getSource();
		
		int msgType = msg.getMsgType();
		String msgTypeString = new String();
		switch(msgType)
		{
		case 0: msgTypeString = "MSG_INQUIRY";
				break;
		case 1: msgTypeString = "MSG_UPDATE";
				break;		
		case 2: msgTypeString = "MSG_RESPONSE";
				break;		
		case 3: msgTypeString = "MSG_REGISTER";
				break;
		default:
				msgTypeString = "INVALIDE MSG TYPE";
				break;
		}
		
		String domainName = msg.getDomainName();
		
		String ip = msg.getIp_address();
		String result;
		if(msg.getResult() == 1)			
		   result = "SUCCESS";
		else
			result = "FAILURE";
		
		boolean messageSent = false;
		if(source.equals(Constants.SECONDARY))
			messageSent = true;
		
		if(messageSent)
			System.out.println("--------------------Message Sent-----------------------");
		else
			System.out.println("--------------------Message Received-------------------");
					
		System.out.println("MSG SOURCE : "+source+
						   "\nMSG TYPE   : "+msgTypeString+					
						   "\nDOMAIN NAME: "+domainName+
						   "\nIP ADDRESS : "+ip);
		if(messageSent)
		System.out.println("RESULT	   : "+result);	
						  
		
		System.out.println("--------------------------------------------------------");		
	}	
}
